--- @param extension Package
--- @param HY HY_Utility
--- @param U Utility
return function(extension, HY, U)
    local hy_kaku_seiga = General:new(extension, "hy_kaku_seiga", "chi_k", 3, 3, General.Female)

    local dive_wall = fk.CreateSkill {
        name = "dive_wall",
    }
    dive_wall:addEffect(fk.RoundStart, {
        can_trigger = function(self, event, target, player, data)
            return player:hasSkill(dive_wall.name)
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            local targets = room:askToChoosePlayers(player, {
                targets = room:getOtherPlayers(player),
                min_num = 1,
                max_num = 1,
                skill_name = dive_wall.name,
                prompt = "dive_wall_prompt"
            })
            if #targets == 1 then
                event:setCostData(self, targets[1])
                return true
            end
        end,
        on_use = function(self, event, target, player, data)
            local room = player.room
            local skillTarget = event:getCostData(self)
            local distanceChoice = "dive_wall_distance::" .. skillTarget.id
            local trickChoice = "dive_wall_trick::" .. skillTarget.id
            local choices = { distanceChoice, trickChoice }
            local result = room:askToChoice(player, {
                choices = choices,
                skill_name = dive_wall.name
            })
            if result == distanceChoice then
                room:setPlayerMark(skillTarget, "@dive_wall", "dive_wall_distance_short")
                room:removeTableMark(player, "dive_wall_trick", skillTarget.id)
                room:addTableMarkIfNeed(player, "dive_wall_distance", skillTarget.id)
            elseif result == trickChoice then
                room:setPlayerMark(skillTarget, "@dive_wall", "dive_wall_trick_short")
                room:removeTableMark(player, "dive_wall_distance", skillTarget.id)
                room:addTableMarkIfNeed(player, "dive_wall_trick", skillTarget.id)
            end
        end
    })
    dive_wall:addEffect(fk.Damaged, {
        can_trigger = function(self, event, target, player, data)
            return player:hasSkill(dive_wall.name) and target == player
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            local targets = room:askToChoosePlayers(player, {
                targets = room:getOtherPlayers(player),
                min_num = 1,
                max_num = 1,
                skill_name = dive_wall.name,
                prompt = "dive_wall_prompt"
            })
            if #targets == 1 then
                event:setCostData(self, targets[1])
                return true
            end
        end,
        on_use = function(self, event, target, player, data)
            local room = player.room
            local skillTarget = event:getCostData(self)
            local distanceChoice = "dive_wall_distance::" .. skillTarget.id
            local trickChoice = "dive_wall_trick::" .. skillTarget.id
            local choices = { distanceChoice, trickChoice }
            local result = room:askToChoice(player, {
                choices = choices,
                skill_name = dive_wall.name
            })
            if result == distanceChoice then
                room:setPlayerMark(skillTarget, "@dive_wall", "dive_wall_distance_short")
                room:removeTableMark(player, "dive_wall_trick", skillTarget.id)
                room:addTableMarkIfNeed(player, "dive_wall_distance", skillTarget.id)
            elseif result == trickChoice then
                room:setPlayerMark(skillTarget, "@dive_wall", "dive_wall_trick_short")
                room:removeTableMark(player, "dive_wall_distance", skillTarget.id)
                room:addTableMarkIfNeed(player, "dive_wall_trick", skillTarget.id)
            end
        end
    })
    dive_wall:addEffect("distance", {
        fixed_func = function(self, from, to)
            if from:hasSkill(dive_wall.name) and table.contains(from:getTableMark("dive_wall_distance"), to.id) then
                return 1
            end
        end,
    })
    dive_wall:addEffect("prohibit", {
        is_prohibited = function(self, from, to, card)
            if to:hasSkill(dive_wall.name) and table.contains(to:getTableMark("dive_wall_trick"), from.id) and card:isCommonTrick() and card.is_damage_card then
                return true
            end
        end
    })
    dive_wall:addLoseEffect(function(self, player, is_death)
        for _, t in ipairs(player.room:getOtherPlayers(player)) do
            player.room:setPlayerMark(t, "@dive_wall", 0)
        end
    end)

    local revolt_theurgy = fk.CreateSkill {
        name = "revolt_theurgy",
    }
    revolt_theurgy:addEffect(fk.TargetSpecifying, {
        can_trigger = function(self, event, target, player, data)
            return player:hasSkill(revolt_theurgy.name) and target ~= player and data.card:isCommonTrick() and not table.contains(data:getAllTargets(), player) and
                data.card.skill:modTargetFilter(target, player, {}, data.card, { bypass_distances = true }) and data.firstTarget
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            return room:askToSkillInvoke(player, {
                skill_name = revolt_theurgy.name,
                prompt = "revolt_theurgy_prompt::" .. target.id .. ":" .. data.card:toLogString()
            })
        end,
        on_use = function(self, event, target, player, data)
            data:addTarget(player)
            player.room:setCardMark(data.card, revolt_theurgy.name, player.id)
        end
    })
    revolt_theurgy:addEffect(fk.CardUseFinished, {
        is_delay_effect = true,
        can_trigger = function(self, event, target, player, data)
            return player:hasSkill(revolt_theurgy.name) and data.card:getMark(revolt_theurgy.name) == player.id and not target:isNude()
        end,
        on_cost = function(self, event, target, player, data)
            return player.room:askToSkillInvoke(player, {
                skill_name = revolt_theurgy.name,
                prompt = "revolt_theurgy_prompt_from::" .. target.id
            })
        end,
        on_use = function(self, event, target, player, data)
            local room = player.room
            room:setCardMark(data.card, revolt_theurgy.name, 0)
            local fromCard = room:askToChooseCard(player, {
                target = target,
                flag = "he",
                skill_name = revolt_theurgy.name,
            })
            room:obtainCard(player, fromCard, false, fk.ReasonPrey, player, revolt_theurgy.name)
            local toCard = room:askToCards(player, {
                min_num = 1,
                max_num = 1,
                include_equip = true,
                skill_name = revolt_theurgy.name,
                prompt = "revolt_theurgy_prompt_to::" .. target.id,
                cancelable = false
            })
            room:moveCardTo(toCard, Card.PlayerHand, target, fk.ReasonGive, revolt_theurgy.name)
        end,
    })

    local play_dead = fk.CreateSkill {
        name = "play_dead",
    }
    play_dead:addEffect(fk.TargetSpecified, {
        can_trigger = function(self, event, target, player, data)
            return player:hasSkill(play_dead.name) and target == player and player:distanceTo(data.to) <= 1 and not player:isNude() and not data.to:isNude() and
                (player ~= data.to or #player:getCardIds("he") >= 2)
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            local cards = room:askToDiscard(player, {
                min_num = 1,
                max_num = 1,
                include_equip = true,
                skill_name = play_dead.name,
                prompt = "play_dead_prompt::" .. data.to.id,
                skip = true
            })
            if #cards == 1 then
                event:setCostData(self, cards[1])
                return true
            end
        end,
        on_use = function(self, event, target, player, data)
            local room = player.room
            local card
            if data.to == player then
                card = room:askToDiscard(player, {
                    min_num = 1,
                    max_num = 1,
                    include_equip = true,
                    skill_name = play_dead.name,
                    skip = true,
                    cancelable = false,
                    pattern = ".|.|.|.|.|.|^" .. event:getCostData(self)
                })[1]
            else
                card = room:askToChooseCard(player, {
                    target = data.to,
                    flag = "he",
                    skill_name = play_dead.name,
                    prompt = "play_dead_prompt_other::" .. data.to.id
                })
            end
            if Fk:getCardById(card).type == Fk:getCardById(event:getCostData(self)).type then
                local ids = data.card:getTableMark(play_dead.name)
                table.insert(ids, data.to.id)
                room:setCardMark(data.card, play_dead.name, ids)
            end
            room:moveCards({
                    ids = { event:getCostData(self) },
                    from = player,
                    toArea = Card.DiscardPile,
                    moveReason = fk.ReasonDiscard,
                    proposer = player,
                    skillName = play_dead.name
                },
                {
                    ids = { card },
                    from = data.to,
                    toArea = Card.DiscardPile,
                    moveReason = fk.ReasonDiscard,
                    proposer = player,
                    skillName = play_dead.name
                })
        end
    })
    play_dead:addEffect(fk.CardUseFinished, {
        is_delay_effect = true,
        can_trigger = function(self, event, target, player, data)
            return player:hasSkill(play_dead.name) and #data.card:getTableMark(play_dead.name) > 0
        end,
        on_use = function(self, event, target, player, data)
            local room = player.room
            local ids = data.card:getTableMark(play_dead.name)
            room:setCardMark(data.card, play_dead.name, 0)
            for _, id in ipairs(ids) do
                room:drawCards(player, 1, play_dead.name)
                room:drawCards(room:getPlayerById(id), 1, play_dead.name)
            end
        end
    })

    extension:loadSkillSkels { dive_wall, revolt_theurgy, play_dead }
    hy_kaku_seiga:addSkills { "dive_wall", "revolt_theurgy", "play_dead" }

    Fk:loadTranslationTable {
        ["hy_kaku_seiga"] = "霍青娥",
        ["#hy_kaku_seiga"] = "邪中窥道",
        ["illustrator:hy_kaku_seiga"] = "イチルギ",
        ["designer:hy_kaku_seiga"] = "黑曜人形",
        ["cv:hy_kaku_seiga"] = "",

        ["dive_wall"] = "潜壁",
        [":dive_wall"] = "每轮开始时或你受到伤害后，你可以选择一名其他角色并选择一项（只能同时生效一项）：1.你与其距离视为1；2.其不能对你使用伤害类锦囊牌。",
        ["dive_wall_prompt"] = "潜壁：你可以选择一名其他角色",
        ["@dive_wall"] = "潜壁",
        ["dive_wall_distance"] = "你与%dest距离视为1",
        ["dive_wall_trick"] = "%dest不能对你使用伤害类锦囊牌",
        ["dive_wall_distance_short"] = "距离",
        ["dive_wall_trick_short"] = "锦囊",

        ["revolt_theurgy"] = "逆术",
        [":revolt_theurgy"] = "其他角色使用普通锦囊牌指定目标时，若你不为此牌目标，你可以成为此牌目标。若如此做，此牌结算结束后你可以获得其一张牌然后交给其一张牌。",
        ["revolt_theurgy_prompt"] = "逆术：你可以成为%dest使用的%arg的目标",
        ["revolt_theurgy_prompt_from"] = "逆术：你可以获得%dest一张牌",
        ["revolt_theurgy_prompt_to"] = "逆术：你须交给%dest一张牌",

        ["play_dead"] = "伪凋",
        [":play_dead"] = "你使用牌指定距离不大于1的角色为目标后，可以弃置你与其各一张牌：若类型相同，此牌结算结束后你与其各摸一张牌。",
        ["play_dead_prompt"] = "伪凋：你可以弃置你与%dest各一张牌",
        ["play_dead_prompt_other"] = "伪凋：弃置%dest一张牌",
    }
end
